package org.mx;

/**
 * 密码工具类，包括跟密码操作相关的方法。
 *
 * @author : john peng date : 2016/5/29
 */
public class PasswordUtils {
	/**
	 * 默认的构造函数
	 */
	private PasswordUtils() {
		super();
	}

	/**
	 * 运行对称加密/解密工具的入口函数
	 * @param args 运行参数
	 */
	public static void main(String[] args) {
		if (args.length != 3) {
			System.out.println("PasswordUtils <Operate> <Algorithm> <text>");
			System.out.println("  Operate: encrypt | decrypt");
			System.out.println("  Algorithm: sm4 | des | 3des | aes");
			System.exit(0);
		}
		String password = "Edmund!@#123)(*0", value = "";
		boolean encrypt = args[0].equalsIgnoreCase("encrypt");
		switch (args[1]) {
		case "sm4":
			if (encrypt) {
				byte[] buff = SecretUtils.sm4EncryptECB(password, args[2].getBytes());
				value = DigestUtils.toBase64(buff);
			} else {
				byte[] buff = DigestUtils.fromBase64(args[2]);
				buff = SecretUtils.sm4DecryptECB(password, buff);
				value = new String(buff);
			}
			break;
		case "des":
			if (encrypt) {
				byte[] buff = SecretUtils.des56Encrypt(password, args[2].getBytes());
				value = DigestUtils.toBase64(buff);
			} else {
				byte[] buff = DigestUtils.fromBase64(args[2]);
				buff = SecretUtils.des56Decrypt(password, buff);
				value = new String(buff);
			}
			break;
		case "3des":
			if (encrypt) {
				byte[] buff = SecretUtils.desede168Encrypt(password, args[2].getBytes());
				value = DigestUtils.toBase64(buff);
			} else {
				byte[] buff = DigestUtils.fromBase64(args[2]);
				buff = SecretUtils.desede168Decrypt(password, buff);
				value = new String(buff);
			}
			break;
		case "aes":
			if (encrypt) {
				byte[] buff = SecretUtils.aes256Encrypt(password, args[2].getBytes());
				value = DigestUtils.toBase64(buff);
			} else {
				byte[] buff = DigestUtils.fromBase64(args[2]);
				buff = SecretUtils.aes256Decrypt(password, buff);
				value = new String(buff);
			}
			break;
		default:
			System.out.println(String.format("Unsupported algorithm: %s.", args[1]));
			System.exit(0);
		}
		System.out.println(String.format("source: %s\ntarget: %s", args[2], value));
	}

	/**
	 * 密码强度检测，使用：密码长度（是否大于6位）、是否包含数字、小写、大写或者常规符号等字符来进行检测。
	 *
	 * @param password 待检测的密码串
	 * @return 密码强度值，0为最弱，5为最强。
	 */
	public static PasswordStrengthen checkStrengthen(String password) {
		if (StringUtils.isBlank(password)) {
			return PasswordStrengthen.LOW;
		}
		int length = password.length();
		int containTypes = 0;
		if (length > 6) {
			if (password.matches(".*[\\d]+.*")) {
				// 包含了数字
				containTypes++;
			}
			if (password.matches(".*[a-z]+.*")) {
				// 包含了小写字母
				containTypes++;
			}
			if (password.matches(".*[A-Z]+.*")) {
				// 包含了大写字母
				containTypes++;
			}
			if (password.matches(".*[`~!@#$%^&()\\-=_+,./<>?'|{}\\[\\]\\\\]+.*")) {
				// 包含了常规的符号
				containTypes++;
			}
		}
		switch (containTypes) {
		case 4:
			// 长度大于6，有四种组合
			return PasswordStrengthen.HIGHER;
		case 3:
			// 长度大于6，有三种组合
			return PasswordStrengthen.HIGH;
		case 2:
			// 长度大于6，有两种组合
			return PasswordStrengthen.MEDIUM;
		default:
			// 长度大于6，仅有一种组合，或者长度小于6
			return PasswordStrengthen.LOW;
		}
	}

	/**
	 * 密码强度枚举定义
	 */
	public enum PasswordStrengthen {
		/**
		 * 密码强度低
		 */
		LOW,
		/**
		 * 密码强度中
		 */
		MEDIUM,
		/**
		 * 密码强度高
		 */
		HIGH,
		/**
		 * 密码强度较高
		 */
		HIGHER
	}

}
